using System;
using System.Collections.Generic;
using Tycho.Parser.Peg;

namespace Tycho.Grammar {
    public class ProductionLookup : IProductionLookup {
        private IProductionLookup OuterScope;
        private Dictionary<string, IProduction> Productions;

        public ProductionLookup () : this (null) {}

        public ProductionLookup (IProductionLookup outerScope) {
            OuterScope = outerScope;
            Productions = new Dictionary<string, IProduction> ();
        }

        public IProduction Lookup (string name) {
            IProduction production;
            if (Productions.TryGetValue (name, out production)) {
                return production;
            } else if (OuterScope != null) {
                return OuterScope.Lookup (name);
            } else {
                throw new NoSuchProductionException (name);
            }
        }

        public bool Contains (string name) {
            return Productions.ContainsKey (name) || OuterScopeContains (name);
        }

        private bool OuterScopeContains (string name) {
            return OuterScope != null && OuterScope.Contains (name);
        }

        public void Add (string name, IProduction production) {
            if (OuterScope != null) {
                if (OuterScope.Contains (name)) {
                    throw new ProductionAlreadyDefinedException ();
                }
            }

            Productions.Add (name, production);
        }
    }
}